home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume17 / cscript next >
Encoding:
Internet Message Format  |  1989-02-08  |  6.8 KB

  1. Subject:  v17i090:  Record interactive session (using pipes)
  2. Newsgroups: comp.sources.unix
  3. Approved: rsalz@uunet.UU.NET
  4.  
  5. Submitted-by: Kent Forschmiedt <happym!kent>
  6. Posting-number: Volume 17, Issue 90
  7. Archive-name: cscript
  8.  
  9. [  This is like the UCB "script" program except it uses pipes,
  10.    not psuedo-tty's.  Some things break when run underneath it,
  11.    but it's still worthwhile.  I wrote the Makefile.  --r$  ]
  12.  
  13. This is a very generic script recorder.  It works fine on most any Unix
  14. system.  I think I got the original from Unix/World magazine, and I made
  15. it work a lot better and gave it a man page.
  16.  
  17. I don't know if one like this has been posted before.
  18.  
  19. #! /bin/sh
  20. # This is a shell archive.  Remove anything before this line, then unpack
  21. # it by saving it into a file and typing "sh file".  To overwrite existing
  22. # files, type "sh file -c".  You can also feed this as standard input via
  23. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  24. # will see the following message at the end:
  25. #        "End of shell archive."
  26. # Contents:  Makefile cscript.1 cscript.c
  27. # Wrapped by rsalz@fig.bbn.com on Wed Feb  8 17:23:59 1989
  28. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  29. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  30.   echo shar: Will not clobber existing file \"'Makefile'\"
  31. else
  32. echo shar: Extracting \"'Makefile'\" \(146 characters\)
  33. sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  34. X#
  35. X# Makefile for cscript
  36. X#
  37. Xall: cscript
  38. X
  39. Xcscript:    cscript.c
  40. X    $(CC) -o cscript $(CFLAGS) cscript.c
  41. X
  42. Xman: cscript.1
  43. X    nroff -man cscript.1 |col >man
  44. END_OF_FILE
  45. if test 146 -ne `wc -c <'Makefile'`; then
  46.     echo shar: \"'Makefile'\" unpacked with wrong size!
  47. fi
  48. # end of 'Makefile'
  49. fi
  50. if test -f 'cscript.1' -a "${1}" != "-c" ; then 
  51.   echo shar: Will not clobber existing file \"'cscript.1'\"
  52. else
  53. echo shar: Extracting \"'cscript.1'\" \(1439 characters\)
  54. sed "s/^X//" >'cscript.1' <<'END_OF_FILE'
  55. X.TH CSCRIPT 1l
  56. X.SH NAME
  57. Xcscript \- record a terminal session
  58. X.SH SYNOPSIS
  59. X.B cscript [ \-aq ] [ \-s
  60. X.I shell
  61. X.B ] [
  62. X.I file
  63. X.B ]
  64. X.SH DESCRIPTION
  65. X.I Cscript
  66. Xrecords an interactive session in a file as it appears on the tty.
  67. X.PP
  68. XIf
  69. X.I file
  70. Xis specified, the script is recorded in
  71. X.I file.
  72. XOtherwise, the session is recorded in
  73. X.B typescript
  74. Xin the current directory.  
  75. XThe
  76. X.B \-s
  77. Xoption causes
  78. X.I shell
  79. Xto be used instead of that specified by the
  80. X.B SHELL
  81. Xenvironment variable.  If
  82. X.B SHELL
  83. Xis not defined, the default is
  84. X.B /bin/sh.
  85. XOther options and their actions are:
  86. X.TP "\w'\-a\ \ 'u"
  87. X.B \-a
  88. XAppend to the script file.  Otherwise, the file is truncated.
  89. X.TP
  90. X.B \-q
  91. XQuiet mode.  Don't print the time and date at the beginning and
  92. Xend of the script.
  93. X.PD
  94. X.PP
  95. X.SH FILES
  96. X.cc x
  97. X./typescript
  98. Xxcc
  99. X.SH SEE ALSO
  100. Xsh(1), csh(1), ksh(1) or whatever you use.
  101. X.SH DIAGNOSTICS
  102. XVarious complaints when \fIopen\fR(2), \fIfork\fR(2), \fIexec\fR(2),
  103. Xor \fIpipe\fR(2) calls fail.
  104. X.SH BUGS
  105. XUser input and program output are intercepted by different processes;
  106. Xthey might not appear in the same order in the script file as they did
  107. Xon the tty.
  108. X.PP
  109. XThis is a generic version, using only pipes.  It should work on
  110. Xany reasonable imitation of Unix, but knows nothing about sockets,
  111. XStreams or ptys.  Programs which care whether they are talking to
  112. Xa tty might not work right.  Commands like \fIps\fR(1)
  113. Xwhich care about process groups probably won't work right.
  114. END_OF_FILE
  115. if test 1439 -ne `wc -c <'cscript.1'`; then
  116.     echo shar: \"'cscript.1'\" unpacked with wrong size!
  117. fi
  118. # end of 'cscript.1'
  119. fi
  120. if test -f 'cscript.c' -a "${1}" != "-c" ; then 
  121.   echo shar: Will not clobber existing file \"'cscript.c'\"
  122. else
  123. echo shar: Extracting \"'cscript.c'\" \(2905 characters\)
  124. sed "s/^X//" >'cscript.c' <<'END_OF_FILE'
  125. X/*
  126. X * cscript - record a terminal session
  127. X * Author:    Grant Dorman
  128. X * Modified by Ray Swartz
  129. X * Modified by Kent Forschmiedt 20jun88
  130. X */
  131. X#ifndef lint
  132. Xstatic char *sccsid = "@(#)cscript.c    2.2  6/20/88";
  133. X#endif
  134. X
  135. X#include <stdio.h>
  136. X#include <signal.h>
  137. X#include <fcntl.h>
  138. X
  139. X#define SHELL        "/bin/sh"
  140. X#define SCRIPTOUT    "typescript"
  141. X#define SHFLAGS        "-i"
  142. X
  143. Xvoid exit(), perror();
  144. X
  145. Xchar *getenv(), *ctime();
  146. X
  147. Xint fd;                /* record file */
  148. Xchar buf[BUFSIZ];
  149. Xchar *fname;
  150. Xchar *shell;
  151. Xint qflg;
  152. Xint ipd[2], opd[2];    /* pipes */
  153. X
  154. Xmain(argc, argv)
  155. Xint argc; char **argv;
  156. X{
  157. X    int getopt();
  158. X    extern char *optarg;
  159. X    extern int optind;
  160. X
  161. X    int c, oflags;
  162. X
  163. X    oflags = O_WRONLY + O_CREAT + O_TRUNC;
  164. X    shell = (char *)0;
  165. X
  166. X    while ((c = getopt(argc, argv, "aqs:")) != EOF)
  167. X        switch(c) {
  168. X            case 'a':    /* append mode */
  169. X                oflags = O_WRONLY + O_CREAT + O_APPEND;
  170. X                break;
  171. X            case 'q':    /* quiet mode */
  172. X                qflg++;
  173. X                break;
  174. X            case 's':
  175. X                shell = optarg;
  176. X                break;
  177. X            default:
  178. X                fprintf(stderr, "Usage: cscript [-aq] [ -s shell ] [file]\n");
  179. X                exit(3);
  180. X        }
  181. X
  182. X    if (!shell && (shell = getenv("SHELL")) == (char *)0)
  183. X        shell = SHELL;
  184. X
  185. X    fname = (optind < argc) ? argv[optind] : SCRIPTOUT;
  186. X    if ( (fd = open(fname, oflags, 0666)) < 0) {
  187. X        perror("cscript: open");
  188. X        exit(4);
  189. X    }
  190. X
  191. X    if (pipe(ipd) == -1) {
  192. X        perror("cscript: pipe");
  193. X        exit(2);
  194. X    }
  195. X    if (pipe(opd) == -1) {
  196. X        perror("cscript: pipe");
  197. X        exit(2);
  198. X    }
  199. X
  200. X    switch(fork()) {
  201. X        case -1: perror("cscript: fork 1"); exit(1);
  202. X
  203. X        case 0: switch(fork()) {
  204. X            case -1:    perror("cscript: fork 2"); exit(1);
  205. X
  206. X            case 0:        do_stdin(); exit(6);
  207. X            default:    do_shell(); exit(6);
  208. X        }
  209. X        default:    do_stdout(); exit(6);
  210. X    }
  211. X
  212. X    /* NOTREACHED */
  213. X}
  214. X
  215. X
  216. Xdo_stdout()
  217. X{
  218. X    unsigned nread;
  219. X    long time(), tloc;
  220. X
  221. X    /* this process will exit when the pipe closes */
  222. X    signal(SIGHUP, SIG_IGN); /* */
  223. X    signal(SIGINT, SIG_IGN); /* */
  224. X    signal(SIGQUIT, SIG_IGN); /* */
  225. X
  226. X    close(ipd[0]); close(ipd[1]);
  227. X
  228. X    close(0); dup(opd[0]);
  229. X    close(opd[0]); close(opd[1]);
  230. X
  231. X    fprintf(stderr, "Recording...\nExit shell to stop\n");
  232. X
  233. X    while((nread = read(0, buf, sizeof buf)) != 0) {
  234. X        write(1, buf, nread);
  235. X        write(fd, buf, nread);
  236. X    }
  237. X
  238. X    if (!qflg) {
  239. X        time(&tloc);
  240. X        fprintf(stderr, "Script done, file is %s\n", fname);
  241. X        sprintf(buf, "\nScript done %s", ctime(&tloc));
  242. X        write(fd, buf, (unsigned) strlen(buf));
  243. X    }
  244. X
  245. X    exit(0);
  246. X}
  247. X
  248. Xdo_stdin()
  249. X{
  250. X    unsigned nread;
  251. X
  252. X    close(opd[0]); close(opd[1]);
  253. X    close(1); dup(ipd[1]);
  254. X    close(ipd[0]); close(ipd[1]);
  255. X
  256. X    while((nread = read(0, buf, sizeof buf)) != 0) {
  257. X        write(fd, buf, nread);
  258. X        write(1, buf, nread);
  259. X    }
  260. X
  261. X    exit(0);
  262. X}
  263. X
  264. Xdo_shell()
  265. X{
  266. X    long time(), tloc;
  267. X
  268. X    close(0); dup(ipd[0]);
  269. X    close(1); dup(opd[1]);
  270. X    /* mush stderr into stdout pipe */
  271. X    close(2); dup(opd[1]);
  272. X
  273. X    close(opd[0]); close(opd[1]);
  274. X    close(ipd[0]); close(ipd[1]);
  275. X    close(fd);
  276. X
  277. X    if (!qflg) {
  278. X        time(&tloc);
  279. X        fprintf(stderr, "Script started %s", ctime(&tloc));
  280. X    }
  281. X
  282. X    execl(shell, shell, SHFLAGS, 0);
  283. X    perror("cscript: execl");
  284. X    exit(5);
  285. X}
  286. END_OF_FILE
  287. if test 2905 -ne `wc -c <'cscript.c'`; then
  288.     echo shar: \"'cscript.c'\" unpacked with wrong size!
  289. fi
  290. # end of 'cscript.c'
  291. fi
  292. echo shar: End of shell archive.
  293. exit 0
  294.